#include "ExpAST.h"
#include "Globe.h"
#include <iostream>
#include "parser.h"
#include "Globe.h"
#pragma warning(disable:4267)
using std::cout;
using std::endl;
unique_ptr<BaseExpAST> parser::parseShiftExp()
{
    unique_ptr<BaseExpAST>l = parseAddExp();
    while ((this->lexer->next_token() == TOK::SAL) || (this->lexer->next_token() == TOK::SAR))
    {
        unique_ptr<ShiftAST>t(new ShiftAST);
        if (this->lexer->next_token() == TOK::SAL)t->op = ShiftAST::SAL;
        else t->op = ShiftAST::SAR;
        this->lexer->match(this->lexer->next_token());
        t->exp1 = std::move(l);
        t->exp2 = parseAddExp();
        l = std::move(t);
    }
    return l;
}
void ShiftAST::Dump() const
{
    cout << "{\"type\":\"Shift\",\"op\":\"";
    switch (this->op)
    {
    case ShiftAST::SAL:
        cout << "<<";
        break;
    case ShiftAST::SAR:
        cout << ">>";
        break;
    default:break;
    }
    cout << "\"";
    if (this->op == DEFAULT)
    {
        cout << "\"content\":";
        this->exp1->Dump();
    }
    else
    {
        cout << "\"exp1\":";
        this->exp1->Dump();
        cout << ",\"exp2\":";
        this->exp2->Dump();
    }
    cout << "}";
}


bool ShiftAST::is_lval() const
{

    if (this->op == DEFAULT)
        return this->exp1->is_lval();
    return false;
}

void ShiftAST::Analyze() const
{
    this->exp1->Analyze();
    switch (this->op)
    {
    case ShiftAST::SAL:
        GENASM(cmd_code::PUSH, CVR(EAX), cmd_val());
        this->exp2->Analyze();
        GENASM(cmd_code::MOV, CVR(EAX), CVR(ECX));
        GENASM(cmd_code::POP, CVR(EAX), cmd_val());
        GENASM(cmd_code::SAL, CVR(EAX), CVR(CL));
        break;
    case ShiftAST::SAR:
        GENASM(cmd_code::PUSH, CVR(EAX), cmd_val());
        this->exp2->Analyze();
        GENASM(cmd_code::MOV, CVR(EAX), CVR(ECX));
        GENASM(cmd_code::POP, CVR(EAX), cmd_val());
        GENASM(cmd_code::SAR, CVR(EAX), CVR(CL));
        break;
    default:
        break;
    }
}
